<template>
  <div>
    <el-row type="flex" justify="center">
      <el-input v-model="numberString" size="mini"></el-input>
      <el-button type="primary" size="mini" @click="onSubmit">开始排序</el-button>
    </el-row>
    <div id="myChart" :style="{width: '600px', height: '600px'}"></div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      stop: false,
      count: 0,
      myChart: undefined,
      numberString: '1,2,3,6,7,6,5,4',
      numbers: [],
      data: [],
      xData: [],
      option: {
        xAxis: {
          type: 'category',
          data: [],
          animationDuration: 0,
          animationDurationUpdate: 400,
        },
        yAxis: {
          type: 'value'
        },
        series: [{
          // realtimeSort: true,
          data: [{
            value: undefined,
            itemStyle: {
              color: '#6e7074'
            }
          }],
          type: 'bar',
          label: {
            show: true,
            position: 'top'
          }
        }],
        animationDuration: 0,
        animationDurationUpdate: 400
      },
      stateObjectArray: [{
        start: undefined,
        end: undefined,
        keyIndex: undefined,
        data: [],
        finishedList: []
      }]
    }
  },
  components: {},
  mounted() {
    this.initialEcharts()
  },
  watch: {},
  computed: {},
  created() {
  },
  methods: {
    pushStateObject(start, end, keyIndex, data) {
      let lastState = JSON.parse(JSON.stringify(this.stateObjectArray[this.stateObjectArray.length - 1]))
      lastState.start = start
      lastState.end = end
      lastState.keyIndex = keyIndex
      lastState.data = JSON.parse(JSON.stringify(data))

      let list = []
      if (lastState.start === lastState.end) {
        list.push(lastState.start)
      }
      if (this.stateObjectArray[this.stateObjectArray.length - 1] && this.stateObjectArray[this.stateObjectArray.length - 1].finishedList && this.stateObjectArray[this.stateObjectArray.length - 1].finishedList.length > 0) {
        list.push(...this.stateObjectArray[this.stateObjectArray.length - 1].finishedList)
      }

      lastState.finishedList = list
      this.stateObjectArray.push(lastState)
    },
    onSubmit() {
      this.stop = true
      setTimeout(() => {
        this.resetData()
        this.dealWithInput()
        this.getFirstStateObject()
        this.setOption()
        this.sort(0, this.data.length - 1)
        this.stop = false
        this.draw()
      }, 1000)
    },
    draw() {
      let i = 0
      let outLoop = () => {
        if (i >= this.stateObjectArray.length) {
          return
        } else {
          this.drawState(this.stateObjectArray[i])
          setTimeout(() => {
            if (!this.stop) {
              i++;
              outLoop();
            }
          }, 800)
        }
      }
      outLoop()
    },
    drawState(state) {
      let start = state.start
      state.data[start].itemStyle.color = '#5BC49F'
      let end = state.end
      state.data[end].itemStyle.color = '#9287E7'
      let keyIndex = state.keyIndex
      state.data[keyIndex].itemStyle.color = '#FF7C7C'
      if (state.finishedList && state.finishedList.length > 0) {
        for (let i = 0; i < state.finishedList.length; i++) {
          state.data[state.finishedList[i]].itemStyle.color = '#333333'
        }
      }
      this.option.series[0].data = state.data
      this.myChart.setOption(this.option)
    },
    setOption() {
      this.option.xAxis.data = this.xData
      this.option.series[0].data = this.data
      this.myChart.setOption(this.option)
    },
    sort(start, end) {
      if (start > end) {
        return
      }
      let startBack = start
      let endBack = end
      let key = this.data[start].value
      // let key = this.getMedian(start, end)
      // let keyIndex = this.data[start].value === key ? start : this.data[end].value === key ? end : Math.floor((start + end) / 2)
      //
      // this.swap(keyIndex, start)
      let keyIndex = start
      this.pushStateObject(start, end, keyIndex, this.data)
      while (start < end) {
        while (this.data[end].value >= key && end > start) {
          end--;
          this.pushStateObject(start, end, keyIndex, this.data)
        }
        if (start < end) {
          this.data[start].value = this.data[end].value
          // this.swap(keyIndex, end)
          // keyIndex = end
          this.pushStateObject(start, end, keyIndex, this.data)
        }
        while (this.data[start].value < key && start < end) {
          start++;
          this.pushStateObject(start, end, keyIndex, this.data)
        }
        if (start < end) {
          this.data[end].value = this.data[start].value
          // this.swap(start, keyIndex)
          // keyIndex = start
          this.pushStateObject(start, end, keyIndex, this.data)
        }
      }
      this.data[start].value = key;
      this.pushStateObject(start, end, start, this.data)
      this.sort(startBack, end - 1)
      this.sort(start + 1, endBack)
    },

    swap(index1, index2) {
      let t = JSON.parse(JSON.stringify(this.data[index1].value))
      let x = JSON.parse(JSON.stringify(this.data[index2].value))
      this.data[index1].value = x;
      this.data[index2].value = t;
    },
    getMedian(start, end) {
      let startValue = this.data[start].value
      let endValue = this.data[end].value
      let midValue = this.data[Math.floor((start + end) / 2)].value
      if (startValue > endValue) {
        let t = startValue
        startValue = endValue
        endValue = t
      }
      if (midValue > endValue) {
        let t = midValue
        midValue = endValue
        endValue = t;
      }
      return startValue > midValue ? startValue : midValue
    },
    resetData() {
      this.xData = []
      this.option.xAxis.data = []
      this.option.series[0].data = []
      this.data = []
      this.start = 0
      this.end = 0
      this.key = 0
      this.stateObjectArray = [{
        start: 0,
        end: 0,
        keyIndex: 0,
        data: [],
        finishedList: []
      }]
    },
    getFirstStateObject() {
      let x = JSON.parse(JSON.stringify(this.data));
      x.finishedList = new Array()
      this.stateObjectArray[0].data = x;
    },
    dealWithInput() {
      // 转为数字
      let numbers = this.numberString.split(',').map(x => parseInt(x)).filter(m => this.isRealNum(m))
      // 获取series[0].data数据
      this.data = numbers.map(x => {
        return {
          value: x, itemStyle: {
            color: '#6e7074'
          }
        }
      })
      // 获取x轴数值
      for (let i = 0; i < numbers.length; i++) {
        this.xData.push(i)
      }
    },
    isRealNum(value) {
      if (value === '' || value === null) {
        return false
      }
      return !isNaN(value) && typeof value === 'number'
    },
    initialEcharts() {
      var chartDom = document.getElementById('myChart');
      this.myChart = this.$echarts.init(chartDom)
      // this.option && this.myChart.setOption(this.option);
    }
  }
}
</script>
<style>

</style>
